package com.ruoyi.demo.controller;

import cn.afterturn.easypoi.word.WordExportUtil;
import cn.dev33.satoken.annotation.SaCheckPermission;
import cn.hutool.core.io.IoUtil;
import cn.hutool.core.util.ZipUtil;
import com.alibaba.fastjson.JSONObject;
import com.ruoyi.common.core.domain.R;
import com.ruoyi.common.core.exception.ServiceException;
import com.ruoyi.common.core.service.DictService;
import com.ruoyi.common.core.utils.file.FileUtils;
import com.ruoyi.common.core.validate.AddGroup;
import com.ruoyi.common.core.validate.EditGroup;
import com.ruoyi.common.core.web.controller.BaseController;
import com.ruoyi.common.excel.utils.ExcelUtil;
import com.ruoyi.common.log.annotation.Log;
import com.ruoyi.common.log.enums.BusinessType;
import com.ruoyi.common.mybatis.core.page.PageQuery;
import com.ruoyi.common.mybatis.core.page.TableDataInfo;
import com.ruoyi.common.oss.core.OssClient;
import com.ruoyi.common.oss.factory.OssFactory;
import com.ruoyi.demo.domain.bo.TestCaseBo;
import com.ruoyi.demo.domain.vo.TestCaseVo;
import com.ruoyi.demo.service.ITestCaseService;
import com.ruoyi.system.api.RemoteDictService;
import com.ruoyi.system.api.domain.SysDictData;
import lombok.RequiredArgsConstructor;
import org.apache.dubbo.config.annotation.DubboReference;
import org.apache.poi.xwpf.usermodel.XWPFDocument;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;

import javax.servlet.http.HttpServletResponse;
import javax.validation.constraints.NotEmpty;
import javax.validation.constraints.NotNull;
import java.io.*;
import java.nio.charset.StandardCharsets;
import java.util.Arrays;
import java.util.List;
import java.util.Optional;

/**
 * 案件管理控制器
 * 前端访问路由地址为:/demo/case
 *
 * @author ruoyi
 * @date 2023-04-21
 */
@Validated
@RequiredArgsConstructor
@RestController
@RequestMapping("/case")
public class TestCaseController extends BaseController {

    private final ITestCaseService iTestCaseService;

    @DubboReference
    private RemoteDictService remoteDictService;


    /**
     * 查询案件管理列表
     */
    @SaCheckPermission("demo:case:list")
    @GetMapping("/list")
    public TableDataInfo<TestCaseVo> list(TestCaseBo bo, PageQuery pageQuery) {
        return iTestCaseService.queryPageList(bo, pageQuery);
    }

    /**
     * 导出案件管理列表
     */
    @SaCheckPermission("demo:case:export")
    @Log(title = "案件管理", businessType = BusinessType.EXPORT)
    @PostMapping("/export")
    public void export(TestCaseBo bo, HttpServletResponse response) {
        List<TestCaseVo> list = iTestCaseService.queryList(bo);
        ExcelUtil.exportExcel(list, "案件管理", TestCaseVo.class, response);
    }

    /**
     * 获取案件管理详细信息
     *
     * @param id 主键
     */
    @SaCheckPermission("demo:case:query")
    @GetMapping("/{id}")
    public R<TestCaseVo> getInfo(@NotNull(message = "主键不能为空") @PathVariable Long id) {
        return R.ok(iTestCaseService.queryById(id));
    }

    /**
     * 新增案件管理
     */
    @SaCheckPermission("demo:case:add")
    @Log(title = "案件管理", businessType = BusinessType.INSERT)
    @PostMapping()
    public R<Void> add(@Validated(AddGroup.class) @RequestBody TestCaseBo bo) {
        return toAjax(iTestCaseService.insertByBo(bo));
    }

    /**
     * 修改案件管理
     */
    @SaCheckPermission("demo:case:edit")
    @Log(title = "案件管理", businessType = BusinessType.UPDATE)
    @PutMapping()
    public R<Void> edit(@Validated(EditGroup.class) @RequestBody TestCaseBo bo) {
        return toAjax(iTestCaseService.updateByBo(bo));
    }


    /**
     * 制作文书
     */
    @SaCheckPermission("demo:case:make")
    @Log(title = "案件管理", businessType = BusinessType.OTHER)
    @GetMapping("/make")
    public void make(@RequestParam("caseId") Long caseId, @RequestParam("templateOssUrls") String templateOssUrls,
                     @RequestParam("templateNames") String templateNames, HttpServletResponse response) {
        TestCaseVo testCase = iTestCaseService.queryById(caseId);
        if (testCase == null) {
            throw new IllegalArgumentException("未找到对应案件信息!");
        }
        List<SysDictData> typeDicts = remoteDictService.selectDictDataByType("demo_type");
        List<SysDictData> statusDicts = remoteDictService.selectDictDataByType("demo_status");
        List<SysDictData> curSexDicts = remoteDictService.selectDictDataByType("demo_cur_sex");
        File[] fileList = new File[templateOssUrls.split(",").length];
        for (int i = 0; i < templateOssUrls.split(",").length; i++) {
            String url = templateOssUrls.split(",")[i];
            OssClient storage = OssFactory.instance();
            FileOutputStream tempOs = null;
            FileOutputStream os = null;
            try (InputStream inputStream = storage.getObjectContent(url)) {
                int available = inputStream.available();
                String tempFilePath = "/tempModel/" + url.split("/")[url.split("/").length - 1];
                File templateFile = new File(tempFilePath);
                FileUtils.mkdir(templateFile);
                if (templateFile.exists()) {
                    FileUtils.del(templateFile);
                }
                //保存模板文件
                tempOs = new FileOutputStream(templateFile);
                IoUtil.copy(inputStream, tempOs, available);
                //填充生成文件
                File genFile = new File("/tempGen/" + templateNames.split(",")[i]);
                if (genFile.exists()) {
                    FileUtils.del(genFile);
                }
                JSONObject setData = JSONObject.parseObject(JSONObject.toJSONString(testCase));
//                setData.put("type_dict", dictService.getDictLabel("demo_type", testCase.getType()));
//                setData.put("status_dict", dictService.getDictLabel("demo_status", testCase.getStatus()));
//                setData.put("curSex_dict", dictService.getDictLabel("demo_cur_sex", testCase.getType()));
                Optional<String> typeName = typeDicts.stream().filter(s -> s.getDictValue().equals(setData.getString("type"))).map(SysDictData::getDictLabel).findAny();
                typeName.ifPresent(s -> setData.put("type_dict", s));
                Optional<String> statusName = statusDicts.stream().filter(s -> s.getDictValue().equals(setData.getString("status"))).map(SysDictData::getDictLabel).findAny();
                statusName.ifPresent(s -> setData.put("status_dict", s));
                Optional<String> curSexName = curSexDicts.stream().filter(s -> s.getDictValue().equals(setData.getString("curSex"))).map(SysDictData::getDictLabel).findAny();
                curSexName.ifPresent(s -> setData.put("curSex_dict", s));
                os = new FileOutputStream(genFile);
                XWPFDocument doc = WordExportUtil.exportWord07(tempFilePath, setData);
                doc.write(os);
                fileList[i] = genFile;
            } catch (Exception e) {
                throw new ServiceException(e.getMessage());
            } finally {
                if (tempOs != null) {
                    try {
                        tempOs.close();
                    } catch (IOException ex) {
                        ex.printStackTrace();
                    }
                }
                if (os != null) {
                    try {
                        os.close();
                    } catch (IOException ex) {
                        ex.printStackTrace();
                    }
                }
            }
        }
        File zipFile = new File("/tempZip/制作文书.zip");
        if (zipFile.exists()) {
            FileUtils.del(zipFile);
        }
        ZipUtil.zip(zipFile, StandardCharsets.UTF_8, false, fileList);
        response.setCharacterEncoding("UTF-8");
        response.setContentType("application/octet-stream;charset=utf-8");
        response.setHeader("Content-disposition", "attachment;filename=制作文书.zip");
        FileInputStream in = null;
        try {
            in = new FileInputStream(zipFile);
            byte[] a = new byte[2048];
            int b;
            while ((b = in.read(a)) != -1) {
                response.getOutputStream().write(a, 0, b);
            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            if (null != in) {
                try {
                    in.close();
                } catch (IOException e2) {
                    System.out.println("关闭输入流错误");
                }
                try {
                    response.getOutputStream().close();
                } catch (IOException e) {
                    System.out.println("输出流关闭错误");
                }
            }
        }
    }

    /**
     * 删除案件管理
     *
     * @param ids 主键串
     */
    @SaCheckPermission("demo:case:remove")
    @Log(title = "案件管理", businessType = BusinessType.DELETE)
    @DeleteMapping("/{ids}")
    public R<Void> remove(@NotEmpty(message = "主键不能为空") @PathVariable Long[] ids) {
        return toAjax(iTestCaseService.deleteWithValidByIds(Arrays.asList(ids), true));
    }
}
